package com.miskatmobile.bb.linkedin;

import java.io.IOException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.microedition.io.HttpConnection;

import net.rim.blackberry.api.browser.URLEncodedPostData;
import net.rim.device.api.crypto.CryptoTokenException;
import net.rim.device.api.crypto.CryptoUnsupportedOperationException;
import net.rim.device.api.crypto.HMAC;
import net.rim.device.api.crypto.HMACKey;
import net.rim.device.api.crypto.RandomSource;
import net.rim.device.api.crypto.SHA1Digest;
import net.rim.device.api.io.Base64OutputStream;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.util.Arrays;
import net.rim.device.api.util.Comparator;

public class OAuthLibrary {

	//public static final String AUTHORIZE_URL = "http://twitter.com/oauth/authorize?oauth_token=";
	//public static final String ACCESS_TOKEN_URL = "http://twitter.com/oauth/access_token"; 
	private static final String SIGNATURE_METHOD = "HMAC-SHA1";
	//public static String STATUS = "status";
	//public static String INREPLY = "in_reply_to_status_id";

    private static final String consumerKey = /*"fR5sSmgSQ8qrczJBvTfqpgoIshPFd1hvLUuBwbMR0T9RpxODr82gDZqvzUzUAQzi";*/"th67e7nk6taa";
	private static final String consumerSecret = /*"dvhqYVEdgpTX4n3DsxPgZ48J5Jiq53pqhGxAjn3zwnN7zedheKt6o3lif56vRPXg";*/"fxuavB0sWkNj9iAf";
	private static String token = null;
	private static String tokenSecret = null;
	
	private static final String OAUTH_CONSUMER_KEY = "oauth_consumer_key";
	private static final String OAUTH_SIGNATURE_METHOD = "oauth_signature_method";
	private static final String OAUTH_SIGNATURE = "oauth_signature";
	private static final String OAUTH_TIMESTAMP = "oauth_timestamp";
	public static final String OAUTH_TOKEN = "oauth_token";
	private static final String OAUTH_NONCE = "oauth_nonce";
	private static final String OAUTH_VERSION = "oauth_version";
	public static final String OAUTH_TOKEN_SECRET = "oauth_token_secret";
	private static final String OAUTH_CALL_BACK = "oauth_callback";
	
	
	public void setTokenWithSecret(String token, String secret){
		OAuthLibrary.token = token;
		OAuthLibrary.tokenSecret = secret;
	}
	
	public String createHeader(String url, String method, Hashtable params) {
		
		String nonce = nonce();
		long timestamp = timestamp();
		Hashtable pairs = new Hashtable();

		pairs.put(OAUTH_CONSUMER_KEY, consumerKey);
		pairs.put(OAUTH_NONCE, nonce);
		pairs.put(OAUTH_SIGNATURE_METHOD, SIGNATURE_METHOD);
		pairs.put(OAUTH_TIMESTAMP, Long.toString(timestamp));
		
		Enumeration e = params.keys();
		URLEncodedPostData parameters = new URLEncodedPostData("utf-8", false);
		//int i = 0;

		while (e.hasMoreElements()) {
			String key = (String) e.nextElement();
			String val = (String) params.get(key);
			pairs.put(key, val);
			
//			headers.append("Authorization", header);
//			//Dialog.alert(headers.toString());
			parameters.append(key, val);
		}
		
		if (token != null) {
			pairs.put(OAUTH_TOKEN, token);
			// pairs.put(OAUTH_VERIFIER, verifier);
		}
		
		pairs.put(OAUTH_VERSION, "1.0");

		String sig = signature(method, url, pairs);
		// pairs.put(OAUTH_SIGNATURE, escape(sig));

		StringBuffer header_sb = new StringBuffer();
		if (method.equals(HttpConnection.GET)) {
			header_sb.append(OAUTH_CONSUMER_KEY).append("=")
					.append(URLUTF8Encoder.encode(consumerKey))
					.append("&");
			header_sb.append(OAUTH_NONCE).append("=").append(nonce)
					.append("&");
			header_sb.append(OAUTH_SIGNATURE).append("=")
					.append(URLUTF8Encoder.encode(sig)).append("&");
			header_sb.append(OAUTH_SIGNATURE_METHOD).append("=")
					.append(URLUTF8Encoder.encode(SIGNATURE_METHOD))
					.append("&");
			//header_sb.append(OAUTH_CALL_BACK).append("=").append("oob").append("&");
			header_sb.append(OAUTH_TIMESTAMP).append("=")
					.append(Long.toString(timestamp)).append("&");
			if (token != null) {
				header_sb.append(OAUTH_TOKEN).append("=")
						.append(URLUTF8Encoder.encode(token)).append("&");
			}
			header_sb.append(OAUTH_VERSION).append("=").append("1.0");
		} else if (method.equals("POST")) {
			header_sb.append(OAUTH_CONSUMER_KEY).append("=")
					.append(URLUTF8Encoder.encode(consumerKey))
					.append("&");
			header_sb.append(OAUTH_NONCE).append("=").append(nonce)
					.append("&");
			header_sb.append(OAUTH_SIGNATURE).append("=")
					.append(URLUTF8Encoder.encode(sig)).append("&");
			header_sb.append(OAUTH_SIGNATURE_METHOD).append("=")
					.append(URLUTF8Encoder.encode(SIGNATURE_METHOD))
					.append("&");
			header_sb.append(OAUTH_TIMESTAMP).append("=")
					.append(Long.toString(timestamp)).append("&");
			if (token != null) {
				header_sb.append(OAUTH_TOKEN).append("=")
						.append(URLUTF8Encoder.encode(token)).append("&");
				// header_sb.append(OAUTH_VERIFIER).append("=").append(escape(verifier)).append("&");
			}
			header_sb.append(OAUTH_VERSION).append("=").append("1.0");
		}
		
		//Dialog.alert(header_sb.toString());
		return header_sb.toString() + "&" + parameters.toString();
	}

	private String signature(String method, String requestURL, Hashtable pairs) {
		StringBuffer sb = new StringBuffer();
		String[] keys = new String[pairs.size()];
		Enumeration e = pairs.keys();
		int i = 0;

		while (e.hasMoreElements()) {
			String k = (String) e.nextElement();
			keys[i++] = escapeURIPathParam(k) + "%3D" + escapeURIPathParam((String) pairs.get(k));
		}
		Arrays.sort(keys, new Comparator() {
			public int compare(Object arg0, Object arg1) {
				return ((String) arg0).compareTo((String) arg1);
			}
		});
		for (i = 0; i < keys.length; i++) {
			sb.append(keys[i]).append("%26");
		}
		//URLEncodedPostData encoder = new URLEncodedPostData("utf-8", false);
		
		sb.delete(sb.length() - 3, sb.length());
		//String data = sb.toString().substring(0, sb.toString().length()-3);
		String msg = method.toUpperCase() + "&"
				+ escapeURIPathParam(requestURL) + "&"
				+ (sb.toString());
		//System.out.println(msg);

		StringBuffer key = new StringBuffer();
		if (consumerSecret != null)
			key.append(URLUTF8Encoder.encode(consumerSecret));
		key.append('&');

		if (tokenSecret != null) {
			key.append(URLUTF8Encoder.encode(tokenSecret));
		}

		//Dialog.alert("Base String:\n"+msg);
		try {
			return hmacsha1(key.toString(), msg);
		} catch (Exception ex) {
			return null;
		}
	}

	private String hmacsha1(String key, String message)
			throws CryptoTokenException, CryptoUnsupportedOperationException,
			IOException {
		HMACKey k = new HMACKey(key.getBytes());
		HMAC hmac = new HMAC(k, new SHA1Digest());
		hmac.update(message.getBytes());
		byte[] mac = hmac.getMAC();
		return Base64OutputStream.encodeAsString(mac, 0, mac.length, false,
				false);
	}

	private String nonce() {
		return Long.toString(Math.abs(RandomSource.getLong()));
	}

	private long timestamp() {
		return new Date().getTime() / 1000;
	}
	
	public  String concatURL(String url, String header){
		String newurl=url;
		header = header.replace(',', '&');
		newurl = newurl+"?"+header;
		return newurl;
	}
	
	public  String escapeURIPathParam(String input) {
		  StringBuffer resultStr = new StringBuffer();
		  char[] arrChar = input.toCharArray();
		  for (int i=0 ; i < arrChar.length; i++) {
			  char ch = arrChar[i];
		   if (isUnsafe(ch)) {
		    resultStr.append('%');
		    resultStr.append(toHex(ch / 16));
		    resultStr.append(toHex(ch % 16));
		   } else{
		    resultStr.append(ch);
		   }
		  }
		  return resultStr.toString();
		 }

		 private  char toHex(int ch) {
		  return (char) (ch < 10 ? '0' + ch : 'A' + ch - 10);
		 }

		 private  boolean isUnsafe(char ch) {
		  if (ch > 128 || ch < 0)
		   return true;
		  return " %$&+,/:;=?@<>#%".indexOf(ch) >= 0;
		 }
}
